package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.dto.ResponseResult;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.minio.MinIOService;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.media.dto.ArticleDto;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.dto.WmNewsDto;
import com.heima.media.entity.WmChannel;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmSensitive;
import com.heima.media.entity.WmUser;
import com.heima.media.feign.ArticleFeign;
import com.heima.media.service.*;
import org.apache.commons.io.IOUtils;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RQueue;
import org.redisson.api.RedissonClient;
import org.redisson.client.RedisClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.xml.stream.events.DTD;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;


@Service
public class IAuditServiceImpl implements IAuditService {
    @Override
    @Async
    public void audit(WmNews wmNews) {
        //判断人工通过
        // 判断文章的状态 4 人工审核通过  8 审核通过（待发布）
        if (wmNews.getStatus() == 4 || wmNews.getStatus() == 8) {
            if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
                sendDelayMsg(wmNews);
            } else {
                publishArticle(wmNews);
            }
            return;
        }
        //需要提取文章得内容和图片
        Map<String, Object> contentMap = getTextAndImagesByContent(wmNews.getContent());
        String text = (String) contentMap.get("text");//内容
        List<String> images = (List<String>) contentMap.get("image");
        //子管理得敏感词
        boolean wordResult = checkWord(wmNews, text);
        if (!wordResult) return;
        //调用阿里云进行文本审核-->标题+标签+内容文字
        boolean textResult = checkText(wmNews, text);
        //不通过直接返回
        if (!textResult) return;
        //调用阿里云进行图片审核---> 封面图片+内容图片
        //自动状态时内容图片成为封面图片,得去重
        List<ImageDto> imageDtos = JSON.parseArray(wmNews.getImages(), ImageDto.class);
        //遍历
        for (ImageDto imageDto : imageDtos) {
            //内容图片不包含封面图片
            if (!StringUtils.isEmpty(imageDto.getUrl()) && !images.contains(imageDto.getUrl())) {
                //将封面图片保存到内容图片
                images.add(imageDto.getUrl());
            }
        }
        boolean imageResult = checkImage(wmNews, images);
        if (!imageResult) return;
        //审核通过,调用文章微服务保文章
        //判断发布时间是否大于当前系统时间,如果发布时间大于当前系统时间,修改文章状态为8
        if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
            wmNews.setStatus(8);
            iWmNewsService.updateById(wmNews);
            sendDelayMsg(wmNews);
        } else {
            publishArticle(wmNews);
        }
    }

    /**
     * 发送延迟消息
     *
     * @param wmNews
     */
    private void sendDelayMsg(WmNews wmNews) {
        // 创建阻塞队列
        RQueue<String> queue = redissonClient.getBlockingQueue("article-publish");
        // 创建延迟队列
        RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(queue);
        // 使用延迟队列发送延迟消息 参数  消息  延迟时间  时间单位
        // 延迟时间为文章的发布时间-当前系统时间
        Long time = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
        //发送延迟消息
        delayedQueue.offer(JSON.toJSONString(wmNews), time, TimeUnit.MILLISECONDS);
    }

    @Autowired
    private IWmSensitiveService iWmSensitiveService;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 子管理得敏感词
     *
     * @param wmNews
     * @param text
     * @return
     */
    private boolean checkWord(WmNews wmNews, String text) {
        boolean result = true;
        String content = wmNews.getTitle() + wmNews.getLabels() + text;
        //判断表中是否已经有数据
        if (SensitiveWordUtil.dictionaryMap.size() <= 0) {
            //查询数据中所有敏感词数据
            LambdaQueryWrapper<WmSensitive> query = new LambdaQueryWrapper<>();
            query.select(WmSensitive::getSensitives);
            List<String> list = iWmSensitiveService.listObjs(query, o -> o.toString());
            //初始化
            SensitiveWordUtil.initMap(list);
        }
        //校验内容
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if (map.size() > 0) {
            result = false;
            wmNews.setStatus(2);
            Set<String> keySet = map.keySet();
            String join = String.join(",", keySet);
            wmNews.setReason("包含敏感词" + join);
            iWmNewsService.updateById(wmNews);
        }
        // // 遍历
        // for (WmSensitive sensitive : list) {
        //     if(content.contains(sensitive.getSensitives())){
        //         result=false;
        //         wmNews.setStatus(2);
        //         wmNews.setReason("包含敏感词"+sensitive.getSensitives());
        //         iWmNewsService.updateById(wmNews);
        //         break;
        //     }
        // }
        return result;
    }

    @Autowired
    private ArticleFeign articleFeign;
    @Autowired
    private IWmUserService iWmUserService;
    @Autowired
    private IWmChannelService iWmChannelService;

    /**
     * 文章微服务保文章
     *
     * @param wmNews
     */
    private void publishArticle(WmNews wmNews) {
        //构建文章
        ArticleDto dto = new ArticleDto();
        //构建文章属性
        BeanUtils.copyProperties(wmNews, dto);
        WmUser wmUser = iWmUserService.getById(wmNews.getUserId());//通过user得到作者id和名字
        WmChannel wmChannel = iWmChannelService.getById(wmNews.getChannelId());//通过channel得到频道名称
        dto.setId(wmNews.getArticleId());
        dto.setAuthorId(wmUser.getApAuthorId());
        dto.setAuthorName(wmUser.getName());
        dto.setChannelName(wmChannel.getName());
        dto.setLayout(wmNews.getType());
        dto.setFlag(0);
        //前端显示图片根据格式分开+,
        //将图片转成集合对象
        List<String> images = new ArrayList<>();//图片地址
        List<ImageDto> list = JSON.parseArray(wmNews.getImages(), ImageDto.class);
        //遍历数据并在list保存地址
        for (ImageDto imageDto : list) {
            images.add(imageDto.getUrl());
        }
        //将images转成 1.jepg格式
        String imageStr = String.join(",", images);
        dto.setImages(imageStr);
        dto.setLikes(0);
        dto.setCollection(0);
        dto.setComment(0);
        dto.setViews(0);
        dto.setSyncStatus(0);
        dto.setCreatedTime(new Date());
        ResponseResult<Long> responseResult = articleFeign.saveArticle(dto);
        if (responseResult.getCode().equals(AppHttpCodeEnum.SUCCESS.getCode())) {
            //获取文章id
            Long articleId = responseResult.getData();
            if (articleId != null) {
                //审核通过改状态为9
                wmNews.setStatus(9);
                wmNews.setArticleId(articleId);
                //更新
                iWmNewsService.updateById(wmNews);
            }
        }
    }

    @Autowired
    private GreenImageScan greenImageScan;
    @Autowired
    private MinIOService minIOService;

    /**
     * 图片审核---> 封面图片+内容图片
     *
     * @param wmNews
     * @param images
     * @return
     */
    private boolean checkImage(WmNews wmNews, List<String> images) {
        boolean result = false;
        //判断是否有图片
        if (images.size() <= 0) {
            //没有则返回
            return true;
        }
        List<byte[]> imageList = new ArrayList<>();
        try {
            //遍历集合得到图片地址
            for (String image : images) {
                InputStream inputStream = minIOService.download(image);
                //将地址转成字节数组
                byte[] bytes = IOUtils.toByteArray(inputStream);
                imageList.add(bytes);
            }
            Map map = greenImageScan.imageScan(imageList);
            if (map != null) {
                String suggestion = (String) map.get("suggestion");
                switch (suggestion) {
                    case "pass":
                        result = true;
                        break;
                    case "block":
                        wmNews.setStatus(2);
                        String label = (String) map.get("label");
                        wmNews.setReason("阿里云审核失败" + label);
                        break;
                    case "review":
                        wmNews.setStatus(3);
                        iWmNewsService.updateById(wmNews);
                        break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private IWmNewsService iWmNewsService;

    /**
     * 文本审核-->标题+标签+内容文字
     *
     * @param wmNews
     * @param text
     * @return
     */
    private boolean checkText(WmNews wmNews, String text) {
        boolean result = false;
        // 文本审核-->标题+标签+内容文字
        String content = wmNews.getTitle() + wmNews.getLabels() + text;
        try {
            Map map = greenTextScan.greenTextScan(content);
            //得到返回结果
            String suggestion = (String) map.get("suggestion");
            switch (suggestion) {
                case "pass":
                    result = true;
                    break;
                case "block":
                    //审核失败设置状态为2,并告诉原因,跟新数据库
                    wmNews.setStatus(2);
                    String label = (String) map.get("label");
                    wmNews.setReason("阿里云审核失败" + label);
                    iWmNewsService.updateById(wmNews);
                    break;
                case "review":
                    //审核不确定,设置状态为3,转人工
                    wmNews.setStatus(3);
                    iWmNewsService.updateById(wmNews);
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 需要提取文章得内容和图片
     *
     * @param content
     * @return
     */
    private Map<String, Object> getTextAndImagesByContent(String content) {
        //构建map集合
        Map<String, Object> map = new HashMap<>();
        //获取文本内容,拼接在一起
        StringBuilder stringBuilder = new StringBuilder();
        //定义图片地址
        List<String> list = new ArrayList<>();
        //将json数据转成对象集合
        List<ContentDto> dtos = JSON.parseArray(content, ContentDto.class);
        //遍历
        for (ContentDto dto : dtos) {
            //判断得到文章内容
            if (dto.getType().equals("text")) {
                stringBuilder.append(dto.getValue());
            } else {
                list.add(dto.getValue());
            }
        }
        map.put("text", stringBuilder.toString());
        map.put("image", list);
        return map;
    }
}
